package com.moon.back.controller.intercepter;

import cn.hutool.core.util.ObjectUtil;
import com.moon.back.constant.RedisConstant;
import com.moon.back.context.UserContext;
import com.moon.back.entity.UserInfo;
import com.moon.back.exception.UserBusinessErrorEnum;
import com.moon.back.exception.UserBusinessException;
import com.moon.back.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 *
 * @author 16905
 */
@Slf4j
@Configuration
public class GlobalIntercepter implements HandlerInterceptor  {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在请求处理之前进行拦截
        // 返回true表示继续向下执行，返回false则中断执行。
        // DEV_MOON_TOKEN
        String header = request.getHeader("dev-moon-token");

        log.info("header: {}",header);
        ApplicationContext applicationContext = SpringUtil.getApplicationContext();
        RedissonClient redissonClient = (RedissonClient) applicationContext.getBean("redissonClient");

        log.info("getRequestURL: {}",request.getRequestURI());

        // 预检请求 或者是/swagger-ui.html 的请求直接通过，不加拦截
        if(Objects.equals(request.getMethod(), "OPTIONS")  ){
            return Boolean.TRUE;
        }

        if(ObjectUtil.isEmpty(header) || ObjectUtil.isNull(header) ){

            String message = UserBusinessErrorEnum.USER_NOT_LOGIN.getMessage();
            System.out.println("error message:" + message);
            // 错误码不能定义成400 否者会失效
            UserBusinessErrorEnum userBusinessErrorEnum = UserBusinessErrorEnum.USER_NOT_LOGIN;
            throw new UserBusinessException(userBusinessErrorEnum);

        }

        RBucket<UserInfo> redisUserInfo = redissonClient.getBucket( header);

        long expireTime = redisUserInfo.remainTimeToLive();
        log.info("remainTime: {}" , expireTime);

        if (expireTime<0 ) {
            // 过期后删除键
            redisUserInfo.delete();
            UserBusinessErrorEnum userLoginTimeout = UserBusinessErrorEnum.USER_LOGIN_TIMEOUT;
            throw new UserBusinessException(userLoginTimeout);
        }

        RScoredSortedSet<String> sortedSet = redissonClient.getScoredSortedSet(RedisConstant.DEV_INLINE_NUM);
        boolean add = sortedSet.add(System.currentTimeMillis() + expireTime, header);

        if(add){
            log.info("用户添加成功");
        }else{
            log.info("用户已存在");
        }


        UserInfo userInfo = redisUserInfo.get();
        // 封装 ThreadLocal 上下文对象
        // 将对象 保存在 当前线程的上下文中
        UserContext.setUserInfo(userInfo);

        return Boolean.TRUE;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理之后，但在视图渲染之前进行拦截

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整个请求结束之后进行拦截，即在DispatcherServlet渲染了对应的视图之后执行。
        log.info("Request and Response is completed");
    }

}
